package main

import (
	"context"
	"errors"
	"fmt"
	"strings"

	"github.com/dengsgo/math-engine/engine"
	"github.com/wailsapp/wails/v2/pkg/runtime"
)

// App struct
type App struct {
	ctx context.Context
}

// NewApp creates a new App application struct
func NewApp() *App {
	return &App{}
}

// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
}

// Greet returns a greeting for the given name
func (a *App) Greet(name string) string {
	return fmt.Sprintf("Hello %s!", name)
}

func (a *App) SetTheme(dark bool) {
	if dark {
		runtime.WindowSetDarkTheme(a.ctx)
	} else {
		runtime.WindowSetLightTheme(a.ctx)
	}
}

func (a App) Message() {
	dialog, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(dialog)
}

func (a *App) Buttons() [10][]string {
	return [10][]string{
		{"AC", "Del", "%", "^"},
		{"e", "pi", "(", ")"},
		{",", "cot", "sec", "csc"},
		{"sin", "ceil", "floor", "round"},
		{"sqrt", "cbrt", "max", "min"},
		{"tan", "abs", "cos", "÷"},
		{"7", "8", "9", "×"},
		{"4", "5", "6", "-"},
		{"1", "2", "3", "+"},
		{"0", ".", "="}}
}

func (a *App) Exec(expression string) string {

	if expression == "" {
		return ""
	} else {
		expression = strings.Replace(expression, "×", "*", -1)
		expression = strings.Replace(expression, "÷", "/", -1)
	}
	toks, err := engine.Parse(expression)
	if err != nil {
		return "Error"
	}
	ast := engine.NewAST(toks, expression)
	if ast.Err != nil {
		return "Error"
	}
	ar := ast.ParseExpression()
	if ast.Err != nil {
		return "Error"
	}
	r := func(err *error) float64 {
		var res float64
		defer func() {
			if r := recover(); r != nil {
				*err = errors.New("Error")
				fmt.Println(*err)
			}
		}()

		res = engine.ExprASTResult(ar)

		return res
	}(&err)
	if err != nil {
		return err.Error()
	}
	display := fmt.Sprintf("%f", r)
	display = strings.TrimRight(display, "0")
	display = strings.TrimRight(display, ".")

	return display
}
